package cc.rboot.inject.helper;

import cc.rboot._core.helper.ClassHelper;
import cc.rboot._core.holder.AppContextHolder;
import cc.rboot.inject.annotation.InjectSetter;
import cc.rboot.inject.core.ISetterInjector;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.annotation.TableId;
import org.omg.CORBA.FieldNameHelper;
import org.springframework.core.MethodParameter;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

public class InjectSetterHelper {

    private static final String DETAIL_FORMAT_STRING = "yyyy-MM-dd HH:mm:ss";

    private static final String DETAIL_REGEX = "(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9]):(0[0-9]|[1-5][0-9])";

    private static final String PROBABLY_REGEX = "\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0|1])";


    public static boolean supportsInjectDefault(MethodParameter methodParameter) {
        return Objects.requireNonNull(methodParameter.getMethod()).isAnnotationPresent(InjectSetter.class);
    }

    public static <T> void injectSetter(T entity) throws Exception {
        if(entity == null){
            return;
        }
        InjectSetter injectSetter = entity.getClass().getAnnotation(InjectSetter.class);
        if (injectSetter != null) {
            Class<? extends ISetterInjector> injector = injectSetter.injector();
            AppContextHolder.getBean(injector).inject(entity);
        }

        List<Field> fields = ClassHelper.getAllFieldList(entity.getClass());
        for (Field field : fields) {
            field.setAccessible(true);

            if (field.get(entity) != null) {
                continue;
            }

            if (!field.isAnnotationPresent(InjectSetter.class)) {
                continue;
            }

            injectSetter = field.getAnnotation(InjectSetter.class);
            String value = injectSetter.value();
            Class<?> type = field.getType();

            if (String.class.equals(type)) {
                field.set(entity, value);
            } else if (Integer.class.equals(field.getType())) {
                field.set(entity, Integer.parseInt(value));
            } else if (Double.class.equals(type)) {
                field.set(entity, Double.parseDouble(value));
            } else if (LocalDateTime.class.equals(type)) {
                if (StringUtils.hasText(value)) {
                    field.set(entity, stringToLocalDateTime(value));
                } else {
                    field.set(entity, LocalDateTime.now());
                }
            }
        }
    }

    private static LocalDateTime stringToLocalDateTime(String s) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DETAIL_FORMAT_STRING);
        return s == null || "".equals(s) || !Pattern.matches(PROBABLY_REGEX + " " + DETAIL_REGEX, s) ?
                null : LocalDateTime.parse(s, dateTimeFormatter);
    }

}